package com.gomoku.matchingsystem.service.impl.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

@Component
public class MatchingPool extends Thread{
    private static List<Player> players = new ArrayList<>();
    private ReentrantLock lock = new ReentrantLock();
    private final static String startGameUrl = "http://127.0.0.1:3000/pk/startgame/";
    private final static String startAIGameUrl = "http://127.0.0.1:3000/pk/startaigame/";
    private static RestTemplate restTemplate;
    @Autowired
    private void setRestTemplate(RestTemplate restTemplate){
        MatchingPool.restTemplate = restTemplate;
    }
    public void addPlayer(Integer userId,Integer rating,Integer bot_id){
        lock.lock();
        try{
            if(bot_id == 0){
                players.add(new Player(userId, rating, 0));
            }
            else{//人机对战 直接开始游戏
                MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
                data.add("aId",userId.toString());
                data.add("botId",bot_id.toString());
                restTemplate.postForObject(startAIGameUrl,data,String.class);
            }
        }finally {
            lock.unlock();
        }
    }
    public void removePlayer(Integer userId){
        lock.lock();
        try{
            List<Player> newPlayers = new ArrayList<>();
            for(Player player : players){
                if(!player.getId().equals(userId)){
                    newPlayers.add(player);
                }
            }
            players = newPlayers;
        }finally {
            lock.unlock();
        }
    }

    private void increaseWaitingTime(){
        for(Player player:players){
            player.setWaitingtime(player.getWaitingtime()+1);
        }
    }
    private boolean checkMatched(Player a, Player b){
        int ratingDelta = Math.abs(a.getRating() - b.getRating());
        int waitingtime = Math.min(a.getWaitingtime(),b.getWaitingtime());
        return ratingDelta <= waitingtime * 10;
    }
    private void sendResult(Player a,Player b){ //将匹配的两名玩家的id返回
        System.out.println("sendResult: "+ a+ " "+ b);
        MultiValueMap<String,String> data = new LinkedMultiValueMap<>();
        data.add("aId",a.getId().toString());
        data.add("bId",b.getId().toString());
        restTemplate.postForObject(startGameUrl,data,String.class);
    }
    private void matchPlayers(){
        System.out.println("match players: "+players);
        boolean [] used = new boolean[players.size()];
        for(int i=0;i<players.size();i++){
            if(used[i]) continue;
            for(int j=i+1;j< players.size();j++){
                if(used[j]) continue;
                Player a = players.get(i),b = players.get(j);
                if(checkMatched(a,b)){
                    used[i] = used[j] =true;
                    sendResult(a,b);
                    break;
                }
            }
            /**
             * 这是我写的版本
            if(used[i]) continue;
            else {
                used[i] = true;
                for (int j=i+1;j< players.size();j++){
                    if (used[j]) continue;
                    else {
                        used[j]=true;
                        sendResult(players.get(i),players.get(j));
                        break;
                    }
                }
            }
             **/
        }

        List<Player> newPlayers = new ArrayList<>();
        for(int i=0;i< players.size();i++){
            if(!used[i])
                newPlayers.add(players.get(i));
        }
        players = newPlayers;
    }
    @Override
    public void run(){
        while (true){
            try {
                Thread.sleep(1000);
                lock.lock();
                try{
                    increaseWaitingTime();
                    matchPlayers();
                }finally {
                    lock.unlock();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}
